#include "ui/menu.h"
#include "draw.h"
#include "context.h"

using namespace std;
using namespace anip;

// MenuBar

ui::MenuBar::Item::Item(MenuBar& m, const wstring& text):
	WithText((Container*)&m)
{
	setText(text);
}

void ui::MenuBar::Item::processMouseEnter()
{
	if (enabled)
	{
		postSignal({ ui::Signal::Type::NeedsRedraw });
		if (((MenuBar*)_parent)->_active && getSubMenu)
			_spawnMenu();
	}
	WithText::processMouseEnter();
}

void ui::MenuBar::Item::processMouseLeave()
{
	if (enabled)
	{
		postSignal({ ui::Signal::Type::NeedsRedraw });
		if (_menu != nullptr)
		{
			if (!_menu->hovered())
			{
				_menu->markDelete();
				_menu = nullptr;
			}
		}
	}
	WithText::processMouseLeave();
}

void ui::MenuBar::Item::processMouseButton(MouseButton btn, ButtonAction action)
{
	if (enabled)
	{
		postSignal({ ui::Signal::Type::NeedsRedraw });
		if (btn == MouseButton::Left && action == ButtonAction::Down)
		{
			if (onClick) onClick(*this);

			if (_doNotSpawnThisTime)
			{
				((MenuBar*)_parent)->_active = false;
				_doNotSpawnThisTime = false;
			}
			else if (_menu == nullptr && getSubMenu)
			{
				((MenuBar*)_parent)->_active = true;
				_spawnMenu();
			}
		}
	}
	WithText::processMouseButton(btn, action);
}

void ui::MenuBar::Item::_spawnMenu()
{
	_menu = getSubMenu(*this);
	//cout << _menu << endl;
	_menu->setPosition(_menu->parent()->toLocalPos(toAbsolutePos({ 0, _size.y })));
	_menu->isDropdown = true;
	_menu->onDeleting = [&](Control& self)
	{
		if (!_parent->hovered()) ((MenuBar*)_parent)->_active = false;
		_menu = nullptr;
		if (_hover) _doNotSpawnThisTime = true;
		//cout << _menu << endl;
	};
}

void ui::MenuBar::Item::paint()
{
	if (enabled)
	{
		if (_press || _menu != nullptr)
			Draw::rect(_absPos, _size, hoverColor().mulWithoutAlpha(pressFactor));
		else if (_hover)
			Draw::rect(_absPos, _size, hoverColor);
	}

	auto textTex = getTextTexture();
	if (textTex != nullptr)
	{
		color col = enabled ? textColor : r::Menu_LineColor;
		vec2 s = textTex->size();
		vec2 p = _absPos + vec2{ r::MenuBar_Margin, (_size.y - s.y) * 0.5f };
		Draw::text(p, s, *textTex, col);
	}
}

void ui::MenuBar::Item::flow(Flow& f)
{
	setPosition({ f.currentX, 0 });
	auto textTex = getTextTexture();
	if (textTex != nullptr)
	{
		vec2 ts = textTex->size();
		f.lineHeight = max(f.lineHeight, ts.y + 10.0f);
		_size = { ts.x + r::MenuBar_Margin * 2, f.lineHeight };
	}
	f.currentX += _size.x;
}

//void ui::MenuBar::Item::applyTheme(Theme& t)
//{
//	hoverColor = t.color("menu.item.hoverColor");
//	pressFactor = t.value("button.pressFactor");
//	WithText::applyTheme(t);
//}

ui::MenuBar::MenuBar(Container* parent) :
	Control(parent, { 0, 0 })
{
	fixedPosition = true;
	//postSignal({ ui::Signal::Type::NeedsReflow });
	setMargins({ 0, 0 }, { 0, 0 });
	layoutOptions.dock = Control::LayoutOptions::DockType::Top;
}

void ui::MenuBar::clearAllItems()
{
	ANIP_ui_LoopOverChildren(child)
		child->markDelete();
	//postSignal({ ui::Signal::Type::NeedsReflow });
}

void ui::MenuBar::paint()
{
	Draw::rect(_absPos, _size, backColor);

	paintChildren();
}

void ui::MenuBar::flow(Flow& f)
{
	//applyTheme(*ui::Theme::current);

	float oldHeight = _size.y;

	Flow mf((Container&)*this);
	mf.borderLeft = 0;
	mf.currentX = 0;
	mf.currentY = 0;
	ANIP_ui_LoopOverChildren(child)
		child->flow(mf);

	_size = { 200.0f, 30.0f };
	ANIP_ui_LoopOverChildren(child)
	{
		vec2 cs = child->size();
		_size = { max(_size.x, cs.x), 
			max(_size.y, child->position().y + cs.y) };
	}
	//_size += _margin;

	mf = Flow((Container&)*this);
	mf.borderLeft = 0;
	mf.currentX = 0;
	mf.currentY = 0;
	ANIP_ui_LoopOverChildren(child)
		child->flow(mf);

	_pos = f.dockableStart;
	_size.x = f.dockableEnd.x - f.dockableStart.x;
	f.dockableStart.y += _size.y;
}

//void ui::MenuBar::applyTheme(Theme& t)
//{
//	backColor = t.color("menubar.backColor");
//}

// Menu

ui::Menu::Item::Item(Menu& m):
	_menu(m), Control((Container*)&m)
{
	layoutOptions.type = Control::LayoutOptions::Flow;
}

void ui::Menu::Item::_reportSubMenu(Menu* val)
{
	_menu._subMenu = val;
}

ui::Menu* ui::Menu::Item::_getParentSubMenu()
{
	return _menu._subMenu;
}

ui::Menu::Menu(Container* parent, vec2 pos):
	Control(parent, pos)
{
	//postSignal({ ui::Signal::Type::NeedsReflow });
	bringToFront();
	focus();

	setMargins({ 0, 0 }, { 0, 0 });
}

void ui::Menu::clearAllItems()
{
	ANIP_ui_LoopOverChildren(child)
		child->markDelete();
	//postSignal({ ui::Signal::Type::NeedsReflow });
}

void ui::Menu::processDefocus()
{
	if (!_hover)
	{
		markDelete();
	}
	postSignal({ ui::Signal::Type::NeedsRedraw });
	Control::processDefocus();
}

void ui::Menu::paint()
{
	// ANIP_TODO: Menu里鼠标掠过的东西用蓝色高亮，那么Menu下面
	// 投出的阴影里那一部分也应该是暗蓝色，光透过的感觉
	Draw::shadowRect(_absPos + vec2{ 0, r::Menu_ShadowSize * 0.4f }, 
		_size, r::Menu_ShadowColor, r::Menu_ShadowSize);
	Draw::roundedRect(_absPos, _size, roundRadius, backColor);
	if (isDropdown)
		Draw::rect(_absPos, { _size.x, roundRadius }, backColor);

	paintChildren();
}

void ui::Menu::flow(Flow& f)
{
	//applyTheme(*ui::Theme::current);

	Flow mf((Container&)*this);
	mf.borderLeft = 0;
	mf.currentX = 0;
	mf.currentY = 0;
	ANIP_ui_LoopOverChildren(child)
		child->flow(mf);

	_size = { 200.0f, 30.0f };
	ANIP_ui_LoopOverChildren(child)
	{
		vec2 cs = child->size();
		_size = { max(_size.x, cs.x), max(_size.y, child->position().y + cs.y) };
	}
	//_size += _margin;

	mf = Flow((Container&)*this);
	mf.borderLeft = 0;
	mf.currentX = 0;
	mf.currentY = 0;
	ANIP_ui_LoopOverChildren(child)
		child->flow(mf);
}

//void ui::Menu::applyTheme(Theme& t)
//{
//	backColor = t.color("menu.backColor");
//	roundRadius = t.value("menu.roundRadius");
//}